#!/usr/bin/python2
ident = '$Id: form_ui.py 109 2006-06-05 18:46:37Z trevor $'
import wx, wx.gizmos, rex, images, re, common, forms
#from form_components 	import *
from xml.dom	 		import minidom

# Sort BY and Find By
BY_ID		= 0
BY_NAME		= 1

BY_SURVEY_ID	= 0
BY_SURVEY_NAME 	= 1
BY_FORM_ID		= 2
BY_FORM_NAME 	= 3

# Menu bar items
ID_SORTBY		= 101
ID_FINDBY		= 102
ID_FINDBY_TEXT	= 103

ID_DISCONNECT		= 110
ID_RELOAD			= 111

BY_FORM_CREATE		= 121
BY_FORM_EDIT		= 122
BY_FORM_DELETE		= 123
BY_FORM_NEW_SURVEY	= 124
BY_FORM_CLONE		= 125

BY_SURVEY_EDIT		= 131
BY_SURVEY_DELETE	= 132
BY_SURVEY_PUBLISH	= 133
BY_SURVEY_CLONE		= 134


#
class form_tree( wx.gizmos.TreeListCtrl ):
	def __init__( self, parent, id=-1 , style=0 ):
		wx.gizmos.TreeListCtrl.__init__( self, parent, id , style=style)
		self.sortby = BY_ID
		self.ascending = 1
		if wx.Platform == '__WXMAC__':
			font = self.GetMainWindow().GetFont()
			font.SetPointSize( 10 )
			self.GetMainWindow().SetFont( font )
			font = self.GetHeaderWindow().GetFont()
			font.SetPointSize( 10 )
			self.GetHeaderWindow().SetFont( font )

	def OnCompareItems( self, item1, item2 ):
		t1 = self.GetPyData( item1 )
		t2 = self.GetPyData( item2 )
		if ( t1 is None ) or ( t2 is None ): return 0
		#~ if ( t1.object_name == "form" ) and ( self.sortby == BY_STATUS ):
			#~ # Comparing forms, if we are in a by status sort, switch to by name
			#~ v1 = t1["name"]
			#~ v2 = t2["name"]
		#~ else:
		# Comparing surveys,
		if self.sortby == BY_NAME:
			v1 = t1["name"]
			v2 = t2["name"]
		elif self.sortby == BY_ID:
			v1 = t1["id"]
			v2 = t2["id"]

		if v1 < v2:  return -1
		if v1 == v2: return 0
		return 1

class form_control( wx.Panel ):
	def __init__( self, parent, id, account ):
		wx.Panel.__init__( self, parent, id )
		self.parent = parent
		self.account = account
		self.last_objects_found = []
		# Create the menu bar
		self.create_menu_items()
		# Create the list control and set it's image list
		tID = wx.NewId()
		style = wx.TR_HAS_BUTTONS | wx.TR_NO_LINES | wx.TR_HIDE_ROOT | wx.TR_FULL_ROW_HIGHLIGHT
		if wx.Platform == '__WXMSW__':
			style = wx.TR_HAS_BUTTONS  | wx.TR_LINES_AT_ROOT | wx.TR_HIDE_ROOT | wx.TR_FULL_ROW_HIGHLIGHT
		self.tree = form_tree( self, tID, style=style )
		self.tree.AddColumn("id")
		self.tree.AddColumn("name")
		self.tree.SetMainColumn(0)
		self.il = wx.ImageList( 16, 16 )
		self.form_icon = 0
		new_form_bitmap = None
		self.survey_icon = 0
		if self.__class__ == survey_control:
			new_form_bitmap = images.getNewFormBitmap()
			self.form_icon = self.il.Add( images.getFormBitmap() )
			self.survey_icon = self.il.Add( images.getSurveyBitmap() )
		elif self.__class__ == referral_control:
			new_form_bitmap = images.getNewPromotionBitmap()
			self.form_icon = self.il.Add( images.getPromotionBitmap() )
			self.survey_icon = self.il.Add( images.getReferralBitmap() )
		self.tree.SetImageList( self.il )
		self.tree.SetColumnWidth( 0, 80 )
		self.tree.GetMainWindow().Bind( wx.EVT_LEFT_DCLICK, self.OnItemDoubleClick )
		self.tree.GetMainWindow().Bind( wx.EVT_RIGHT_DOWN, self.OnTreeRightClick )
		self.tree.GetMainWindow().Bind( wx.EVT_LEFT_DOWN, self.OnTreeLeftClick )
		self.tree.GetHeaderWindow().Bind( wx.EVT_LEFT_DOWN, self.OnTreeHeaderLeftClick )
		#if wx.Platform != '__WXMAC__':
		self.tree.Bind( wx.EVT_TREE_BEGIN_DRAG, self.OnBeginDrag, id=tID )
		self.topbar = wx.BoxSizer( wx.HORIZONTAL )
		# The new button
		self.new_button = wx.BitmapButton( self, -1, new_form_bitmap, size=common.button_size, style=wx.NO_BORDER )
		self.new_button.Bind( wx.EVT_BUTTON, self.OnFormCreate )
		self.topbar.Add( self.new_button, 0 )
		# The refresh button
		self.refresh_button = wx.BitmapButton( self, -1, images.getRefreshBitmap(), size=common.button_size, style=wx.NO_BORDER )
		self.refresh_button.Bind( wx.EVT_BUTTON, self.reload_forms )
		self.topbar.Add( self.refresh_button, 0 )
		self.topbar.Add( (3,3), 0, wx.EXPAND )
		# The finding selector
		self.findby_choice = wx.Choice( self, ID_FINDBY, choices=self.find_choices )
		self.findby_choice.SetSelection( 0 )
		self.Bind( wx.EVT_CHOICE, self.OnFindByChange, id=ID_FINDBY )
		self.topbar.Add( self.findby_choice, 2, wx.EXPAND )
		self.find_by = 1	# Find by ID by default
		# The find text box
		self.find_text = wx.TextCtrl( self, ID_FINDBY_TEXT, "" )
		self.topbar.Add( self.find_text, 2, wx.EXPAND )
		self.Bind( wx.EVT_TEXT, self.OnFindByTextChange, id=ID_FINDBY_TEXT )
		self.find_text.Bind( wx.EVT_LEFT_DOWN, self.OnFindByTextClick )
		self.find_text.Bind( wx.EVT_KEY_DOWN, self.OnFindByTextKeyPress )
		# zoom button
		self.zoom_button = wx.BitmapButton( self, -1, images.getZoomBitmap(), size=common.button_size, style=wx.NO_BORDER )
		self.zoom_button.Bind( wx.EVT_BUTTON, self.OnZoom )
		self.topbar.Add( self.zoom_button, 0 )
		# The whole mess
		self.sizer = wx.BoxSizer( wx.VERTICAL )
		self.sizer.Add( self.topbar, 0, wx.EXPAND )
		self.sizer.Add( self.tree, 1, wx.EXPAND )
		self.SetSizer( self.sizer )
		self.SetAutoLayout( 1 )
		# Windows needs this call
		self.Layout()
		self.Show()
		self.forms = []
		self.reload_forms()
		self.tree.Bind( wx.EVT_TREE_BEGIN_DRAG, self.OnBeginDrag, id=tID )
	
	def OnTreeLeftClick( self, event ):
		self.tree.Refresh()
		event.Skip()
			
	def OnTreeHeaderLeftClick( self, event ):
		treeitem, thing, column_index = self.tree.HitTest( event.GetPositionTuple() )
		# flip the asc desc?
		if self.tree.sortby == column_index:
			self.tree.ascending = self.tree.ascending * -1
		self.tree.sortby = column_index
		self.tree.SortChildren( self.root )
		# sort the issues
		for frm in self.forms:
			self.tree.SortChildren( frm.tree_item )
			
	def OnBeginDrag( self, event ):
		item = self.tree.GetSelection()
		if item is None: return
		obj = self.tree.GetPyData( item )
		if obj is None: return
		data = wx.PyTextDataObject()
		if  obj.object_name == "form":
			xmlstring = obj.toxml()
			data.SetText( xmlstring )
		elif obj.object_name == "survey":
			linktag = "<#[" + self.sur_url_tag + obj["id"] + "]#>"
			data.SetText( linktag )
		else:
			return
		ds = wx.DropSource( self )
		ds.SetData( data )
		result = ds.DoDragDrop()

	def create_menu_items( self ):
		self.menubar = self.account.window.menubar

	def OnZoom( self, event ):
		if self.account.window: self.account.window.OnZoom( 2 )
		
	def AppendForm( self, frm):
		frm_item = self.tree.AppendItem( self.root, frm["id"] )
		self.tree.SetItemText( frm_item, frm["name"], 1 )
		self.tree.SetItemImage( frm_item, self.form_icon )
		self.tree.SetItemBold( frm_item, 1 )
		# Now, cross link
		self.tree.SetPyData( frm_item, frm )
		return frm_item

	def AppendSurvey( self, frm_item, sur ):
		sur_item = self.tree.AppendItem( frm_item, sur["id"] )
		self.tree.SetItemText( sur_item, sur["name"], 1 )
		self.tree.SetItemImage( sur_item, self.survey_icon )
		# Colorize
		#if self.__class__ is survey_control:
		#	bgcolor="#F5F5FF"
		#	color = "#5555EE"
		#elif self.__class__ is referral_control:
		#	bgcolor="#F5F5FF"
		#	color = "#5555EE"
		#self.tree.SetItemTextColour( sur_item, color )
		#self.tree.SetItemBackgroundColour( sur_item, bgcolor )
		# Now, cross link
		self.tree.SetPyData( sur_item, sur )
		return sur_item

	def reload_forms( self, event=None ):
		# Close off all open child frames
		if not self.CloseAllFrames(): return
		module = ''
		if self.__class__ is survey_control:
			module = 'Survey'
		elif self.__class__ is referral_control:
			module = 'Referral'
		else:
			common.dprint("Failed to determine the form module")
			return
		if self.account.window: self.account.window.SetStatusText( "Getting %ss..." % ( self.parent_object_name.lower() ) )
		wx.Yield()
		# Clear out the current tree
		self.forms = []
		self.tree.DeleteAllItems()
		# Add the root
		self.root = self.tree.AddRoot( self.parent_object_name.capitalize() + "s" )
		# Get the forms
		frms = None
		try:
			cur = wx.BusyCursor()
			xmlstring = self.account.execute( module, "forms_get2")
			xmlstring = common.uni2str( xmlstring )
			pdom 	= minidom.parseString( xmlstring )
			frms	= pdom.firstChild
		except:
			common.show_error("Failed to load %ss" % ( module ) )
		del cur
		if not frms: return
		for pnode in frms.getElementsByTagName("form"):
			frm = rex.forms.form( self.account, module, common.uni2str( pnode.toxml() ) )
			self.forms.append( frm )
			# Create a tree node for the frm object and it's children
			frm_item = self.AppendForm( frm )
			frm.tree_item = frm_item
			# How about it's surveys?
			for sur in frm.surveys:
				sur_item = self.AppendSurvey( frm_item, sur )
				sur.tree_item = sur_item
			self.tree.SortChildren( frm_item )
		self.tree.SortChildren( self.root )
		if self.account.window: self.account.window.SetStatusText( "Ready" )
		self.tree.Refresh()

	def OnFindByChange( self, event ):
		selected = self.findby_choice.GetSelection()
		if selected < 0: return
		if self.root is None: return
		if self.tree.GetChildrenCount( self.root ) < 1: return
		self.find_text.SetValue("")
		self.find_text.SetFocus()

	def OnFindByTextClick( self, event ):
		length = len( self.find_text.GetValue() )
		if length > 0:
			self.find_text.SetSelection( 0, length )
		event.Skip()

	def OnFindByTextKeyPress( self, event ):
		if event.GetKeyCode() == wx.K_RETURN:
			self.OnFindByTextChange( event, True )
			return
		event.Skip()

	def OnFindByTextChange( self, event=None,FindNext= False ):
		if not FindNext: self.last_objects_found = []
		selected = self.findby_choice.GetSelection()
		search_text = self.find_text.GetValue()
		if len( search_text.strip() ) < 1:
			self.tree.UnselectAll()
			return
		# If we are looking for an ID, strip the id entered
		search_text = search_text.strip().replace("\\","\\\\")
		found_something = 0
		if ( selected == 0 ) or ( selected == 2 ):
			prop = "id"
		else:
			prop = "name"
		object = None

		# Create the matcher text
		search_pattern = re.compile( "^%s" % search_text, re.I )
		for frm in self.forms:
			if selected > 1:
				# Match the string in the frm property
				if re.search( search_pattern, frm[ prop ] ) is not None:
					if FindNext and ( frm in self.last_objects_found ): continue
					object = frm
					break
			else:
				# We are doing surveys
				for sur in frm.surveys:
					# Match the string in the survey property
					if re.search( search_pattern, sur[ prop ] ) is not None:
						if FindNext and ( sur in self.last_objects_found ): continue
						object = sur
						break

		# If we found nothing, clear the selection, otherwise, select it
		if object is None:
			self.tree.UnselectAll()
			self.last_objects_found = []
		else:
			self.tree.EnsureVisible( object.tree_item )
			self.tree.SelectItem( object.tree_item )
			self.last_objects_found.append( object )

	def OnClose( self, event ):
		# Decrement the binder sui ref count
		da = self.GetParent().disconnect_account
		if da( self.account.account_manager_aid ) == 1:
			bf = self.account.binder_frame
			bf.ref_count = bf.ref_count -1
			bf.Close()
			cf = self.account.contact_frame
			cf.ref_count = cf.ref_count -1
			cf.Close()
			event.Skip()

	def OnDisconnect( self, event ):
		if self.OnClose( event ):
			self.Destroy()
			
	def OnFormCreate( self, event ):
		module = ''
		if self.__class__ is survey_control:
			module = 'Survey'
		elif self.__class__ is referral_control:
			module = 'Referral'
		else:
			common.show_error("Failed to determine the module")
			return
		frm = rex.forms.form( self.account, module, None )
		# Create the new frm on the server, that will give it an ID
		new_name = "New %s" % self.parent_object_name.capitalize()
		frm.create( new_name )
		self.forms.append( frm )
		# Create a tree node for the frm object and it's children
		frm_item = self.AppendForm( frm )
		frm.tree_item = frm_item
		self.tree.SelectItem( frm_item )
		self.OnFormEdit( None )

	def OnFormClone( self, event ):
		item = self.tree.GetSelection()
		if item is None: return
		frm = self.tree.GetPyData( item )
		if frm is None: return
		if frm.object_name != "form": return
		# Create the new form on the server, that will give it an ID
		new_fid = frm.clone()
		self.reload_forms()

	def OnFormCopy( self, event ):
		item = self.tree.GetSelection()
		if item is None: return
		frm = self.tree.GetPyData( item )
		if frm is None: return
		if frm.object_name != "form": return
		obj = frm.toxml()
		# Now let's put it in the clipboard
		clipdata = wx.TextDataObject()
		clipdata.SetText( obj )
		wx.TheClipboard.Open()
		wx.TheClipboard.SetData( clipdata )
		wx.TheClipboard.Close()
		
	def OnFormEdit( self, event ):
		item = self.tree.GetSelection()
		if item is None: return
		frm = self.tree.GetPyData( item )
		if frm is None: return
		if frm.object_name != "form": return
		if frm.editor is not None:
			# switch to this page
			try: self.account.window.ebook.SetSelection( common.get_page_index( self.account.window.ebook, frm.editor ) )
			except: common.dprint("Failed to switch to editor")
			return
		frm.editor = forms.form( self.account, frm, item )
		# add the page
		self.account.window.ebook.AddPage( frm.editor, frm.editor.get_label_text() )
		pi = common.get_page_index( self.account.window.ebook, frm.editor )
		try:
			self.account.window.ebook.SetSelection( pi )
			self.account.window.ebook.SetPageImage( pi, self.account.window.icon_from_rex_object( frm ) )
		except:
			common.show_error("Failed to switch to editor", False)

	def OnFormDelete( self, event ):
		item = self.tree.GetSelection()
		if item is None: return
		frm = self.tree.GetPyData( item )
		if frm is None: return
		if frm.object_name != "form": return
		# Confirm delete
		dconf = "Are you sure you want to delete this %s and all it's %ss?" % \
				( self.parent_object_name.capitalize(), self.child_object_name.capitalize() )
		res = wx.MessageBox( dconf, "Confirm Delete", wx.YES_NO )
		if res != wx.YES: return
		if frm.delete():
			if frm.editor is not None:
				frm.editor.Destroy()
			for sur in frm.surveys:
				if sur.editor is not None:
					sur.editor.Destroy()
			self.forms.remove( frm )
			self.tree.Delete( item )
			frm = None

	def OnFormNewSurvey( self, event ):
		#print "OnFormNewSurvey"
		item = self.tree.GetSelection()
		if item is None: return
		frm = self.tree.GetPyData( item )
		if frm is None: return
		if frm.object_name != "form":
			# This is really an survey, lets get the frm from it
			if frm.object_name != "survey": return
			frm  = frm.form
			item = frm.tree_item

		#print "Editing frm %s" % frm["name"]
		sur = rex.forms.survey( self.account, frm, None )
		# Create the new survey on the server, that will give it an ID
		sur["form_id"] = frm["id"]
		new_name = "New %s" % self.child_object_name.capitalize()
		sur.create( new_name )
		frm.surveys.append( sur )
		sur_item = self.AppendSurvey( item, sur )
		sur.tree_item = sur_item
		self.tree.Expand( item )
		self.tree.SelectItem( sur_item )
		self.OnSurveyEdit( None )

	def OnSurveyEdit( self, event ):
		item = self.tree.GetSelection()
		if item is None: return
		sur = self.tree.GetPyData( item )
		if sur is None: return
		if sur.object_name != "survey": return
		if sur.editor is not None:
			# switch to this page
			try: self.account.window.ebook.SetSelection( common.get_page_index( self.account.window.ebook, sur.editor ) )
			except: common.dprint("Failed to switch to editor")
			return
		sur.editor = forms.survey( self.account, sur, item )
		#sur.editor = forms.suiSurveyEditor( self.account, sur, item )
		# add the page
		self.account.window.ebook.AddPage( sur.editor, sur.editor.get_label_text() )
		pi = common.get_page_index( self.account.window.ebook, sur.editor )
		try:
			self.account.window.ebook.SetSelection( pi )
			self.account.window.ebook.SetPageImage( pi, self.account.window.icon_from_rex_object( sur ) )
		except:
			common.show_error("Failed to switch to editor", False)

	def OnSurveyClone( self, event ):
		item = self.tree.GetSelection()
		if item is None: return
		sur = self.tree.GetPyData( item )
		if sur is None: return
		if sur.object_name != "survey": return
		frm = sur.form
		# Create the new survey on the server, that will give it an ID
		new_sid = sur.clone()
		if len( new_sid.strip() ) < 1: return
		new_sur = rex.forms.survey( self.account, sur, None )
		new_sur["id"] = new_sid
		new_sur["name"] = "Cloned %s" % sur["name"]
		new_sur["form_id"] = frm["id"]
		new_sur.form = frm
		frm.surveys.append( new_sur )
		sur_item = self.AppendSurvey( frm.tree_item, new_sur )
		new_sur.tree_item = sur_item
		self.tree.Expand( item )
		self.tree.SelectItem( sur_item )
		self.OnSurveyEdit( None )

	def OnSurveyDelete( self, event ):
		item = self.tree.GetSelection()
		if item is None: return
		sur = self.tree.GetPyData( item )
		if sur is None: return
		if sur.object_name != "survey": return
		# Confirm delete
		dconf = "Are you sure you want to delete this %s?" % self.child_object_name.capitalize()
		res = wx.MessageBox( dconf, "Confirm Delete", wx.YES_NO )
		if res != wx.YES: return
		if sur.delete():
			if sur.editor is not None:
				sur.editor.Destroy()
			self.tree.Delete( item )
			sur = None

	def OnSurveyPublish( self, event ):
		item = self.tree.GetSelection()
		if item is None: return
		sur = self.tree.GetPyData( item )
		if sur is None: return
		if sur.object_name != "survey": return
		dlg = newsletter_components.suiPublisher( self, self.account, sur, "SURVEYS" )
		dlg.Show()


	def OnTreeRightClick( self, event ):
		item, where, column = self.tree.HitTest( event.GetPosition() )
		#~ print item
		if item is None: return
		object = self.tree.GetPyData( item )
		if object is None: return
		menu = None
		if object.object_name == "form":
			menu = self.frm_menu
		elif object.object_name == "survey":
			menu = self.sur_menu
		if menu is None: return

		self.tree.EnsureVisible( item )
		self.tree.SelectItem( item )
		self.PopupMenu( menu, wx.Point( event.m_x + 5, event.m_y + 15) )

	def OnItemDoubleClick( self, event ):
		#print "Item double clicked"
		item = self.tree.GetSelection()
		if item is None: return
		object = self.tree.GetPyData( item )
		if object is None: return
		if object.object_name == "form":
			self.OnFormEdit( event )
		elif object.object_name == "survey":
			self.OnSurveyEdit( event )

	def SetTextOfItem( self, item, text ):
		self.tree.SetItemText( item, text )

	def CloseAllFrames( self ):
		'''Cycle through all forms and surveys and close off their frames if any.'''
		for p in self.forms:
			if p.editor is not None:
				f = p.editor
				if f.OnClose( None ):
					f.Destroy()
				else:
					return False
			# Check it's child publications
			for i in p.surveys:
				if i.editor is not None:
					f = i.editor
					if f.OnClose( None ):
						f.Destroy()
					else:
						return False
		return True



####################################################################################################
class survey_control( form_control ):
	def __init__( self, parent, id, account ):
		self.find_choices 		= ["Survey ID", "Survey Name","Form ID", "Form Name"]
		self.sur_url_tag		= "SURVEY_URL_"
		self.child_object_name 	= "Survey"
		self.parent_object_name	= "Form"
		self.icon_name			= "SurveyModule"
		form_control.__init__( self, parent, id, account )

	def create_menu_items( self ):
		form_control.create_menu_items( self )
		# The frm menu
		menu = wx.Menu()
		menu.Append( ID_RELOAD, "&Reload\tCtrl+R", " Reload" )
		self.Bind( wx.EVT_MENU, self.reload_forms, id=ID_RELOAD )
		menu.AppendSeparator()
		menu.Append( BY_FORM_CREATE, "&Create a New Form", " Create a new form" )
		menu.Append( BY_FORM_CLONE, "&Clone", " Clone the selected form" )
		menu.AppendSeparator()
		menu.Append( BY_FORM_EDIT, "&Edit", " Edit the selected form" )
		menu.Append( BY_FORM_DELETE, "&Delete", " Delete the selected form" )
		menu.AppendSeparator()
		menu.Append( BY_FORM_NEW_SURVEY, "&Add New Survey", " Create a new survey in the selected form" )
		self.frm_menu = menu
		self.Bind( wx.EVT_MENU, self.OnFormCreate, id=BY_FORM_CREATE )
		self.Bind( wx.EVT_MENU, self.OnFormClone, id=BY_FORM_CLONE )
		self.Bind( wx.EVT_MENU, self.OnFormEdit, id=BY_FORM_EDIT )
		self.Bind( wx.EVT_MENU, self.OnFormDelete, id=BY_FORM_DELETE )
		self.Bind( wx.EVT_MENU, self.OnFormNewSurvey, id=BY_FORM_NEW_SURVEY )

		# The survey menu
		menu = wx.Menu()
		menu.Append( BY_FORM_NEW_SURVEY, "&Create a New Survey", " Create a new survey in the selected form" )
		menu.Append( BY_SURVEY_CLONE, "Clone", " Clone the selected survey" )
		menu.AppendSeparator()
		menu.Append( BY_SURVEY_EDIT, "&Edit", " Edit the selected survey" )
		menu.Append( BY_SURVEY_DELETE, "&Delete", " Delete the selected survey" )
		menu.Append( BY_SURVEY_PUBLISH, "&Publish", " Publish the selected survey" )
		self.Bind( wx.EVT_MENU, self.OnSurveyEdit, id=BY_SURVEY_EDIT )
		self.Bind( wx.EVT_MENU, self.OnSurveyClone, id=BY_SURVEY_CLONE )
		self.Bind( wx.EVT_MENU, self.OnSurveyDelete, id=BY_SURVEY_DELETE )
		self.Bind( wx.EVT_MENU, self.OnSurveyPublish, id=BY_SURVEY_PUBLISH )
		self.sur_menu = menu

class referral_control( form_control ):
	def __init__( self, parent, id, account ):
		self.find_choices 		= ["Referral ID", "Referral Name","Form ID", "Form Name"]
		self.sur_url_tag		= "REFERRAL_URL_"
		self.child_object_name 	= "Referral"
		self.parent_object_name	= "Promotion"
		self.icon_name			= "ReferralModule"
		form_control.__init__( self, parent, id, account )

	def create_menu_items( self ):
		form_control.create_menu_items( self )
		# The frm menu
		menu = wx.Menu()
		menu.Append( ID_RELOAD, "&Reload\tCtrl+R", " Reload" )
		self.Bind( wx.EVT_MENU, self.reload_forms, id=ID_RELOAD )
		menu.AppendSeparator()
		menu.Append( BY_FORM_CREATE, "&Create a New Promotion", " Create a new promotion" )
		menu.Append( BY_FORM_CLONE, "&Clone", " Clone the selected promotion" )
		menu.AppendSeparator()
		menu.Append( BY_FORM_EDIT, "&Edit", " Edit the selected promotion" )
		menu.Append( BY_FORM_DELETE, "&Delete", " Delete the selected promotion" )
		menu.AppendSeparator()
		menu.Append( BY_FORM_NEW_SURVEY, "&Add New Referral", " Create a new referral request in the selected promotion" )
		self.frm_menu = menu
		self.Bind( wx.EVT_MENU, self.OnFormCreate, id=BY_FORM_CREATE )
		self.Bind( wx.EVT_MENU, self.OnFormClone, id=BY_FORM_CLONE )
		self.Bind( wx.EVT_MENU, self.OnFormEdit, id=BY_FORM_EDIT )
		self.Bind( wx.EVT_MENU, self.OnFormDelete, id=BY_FORM_DELETE )
		self.Bind( wx.EVT_MENU, self.OnFormNewSurvey, id=BY_FORM_NEW_SURVEY )
		# The survey menu
		menu = wx.Menu()
		menu.Append( BY_FORM_NEW_SURVEY, "&Create a New Referral", " Create a new referral request in the selected promotion" )
		menu.Append( BY_SURVEY_CLONE, "Clone", " Clone the selected referral" )
		menu.AppendSeparator()
		menu.Append( BY_SURVEY_EDIT, "&Edit", " Edit the selected referral request" )
		menu.Append( BY_SURVEY_DELETE, "&Delete", " Delete the selected referral request" )
		self.Bind( wx.EVT_MENU, self.OnSurveyEdit, id=BY_SURVEY_EDIT )
		self.Bind( wx.EVT_MENU, self.OnSurveyClone, id=BY_SURVEY_CLONE )
		self.Bind( wx.EVT_MENU, self.OnSurveyDelete, id=BY_SURVEY_DELETE )
		self.sur_menu = menu
